#ifndef AECMODELER_INC_BODY_H
#define AECMODELER_INC_BODY_H

#pragma warning(push)
#pragma warning(disable : 4702) // unreachable code
#include <vector>
#pragma warning(pop)
#include "zentity.h"
#include "ztransf3d.h"
#include "ucolor.h"
#include "zmorphmap.h"
#include "zenums.h"
#include "zglobal.h"

AECMODELER_NAMESPACE_BEGIN

const Flag IPBF   = UEFLAG(0);  // Interval Present            Body Flag  
const Flag NEGBF  = UEFLAG(1);  // Negative                    Body Flag
const Flag DASHBF = UEFLAG(2);  // Display DASHed        lines Body Flag
const Flag WFBF   = UEFLAG(3);  // Display Wireframe           Body Flag
const Flag DAEBF  = UEFLAG(4);  // Display Approximating Edges Body Flag
const Flag DBEBF  = UEFLAG(5);  // Display Bridge        Edges Body Flag


class DllImpExp UeBody : public UeEntity
{
public:
    UeBody();
    UeBody(const UeBody&);
    ~UeBody();
    UeBody& operator =(const UeBody &);
    UeBody copy() const;
    void init(bool  deleteContents);
    bool isValid(int validityCheckingLevel = -1) const;
    UeBody boolOper(UeBody&, UeBoolOperType eType, bool  hideZeroSlopeEdges = true, UeTopologyChangeCallback* pCallBack = NULL, bool  keepInputBodiesWhenFails = UeKeepInputBodiesWhenBooleanOperationsFail());
    UeBody operator + (const UeBody& );
    UeBody  operator - (const UeBody& );
    UeBody  operator * (const UeBody& );
    UeBody& operator +=(const UeBody& );
    UeBody& operator -=(const UeBody& );
    UeBody& operator *=(const UeBody& ); 
    UeBody& transform(const UeTransf3d&);
    UeBody operator -();
    static UeBody box (const UePoint3d& corner, const UeVector3d& sizes);
    static UeBody sphere (const UePoint3d& center, double radius, int approx);
    static UeBody cylinder(const UeLine3d&axis, double radius, int approx);
    static UeBody cylinder(const UeLine3d&axis, const UeVector3d& baseNormal,double radius, int approx);
    static UeBody cone(const UeLine3d&axis, double radius1, double radius2, int approx);
    static UeBody cone(const UeLine3d&axis, const UeVector3d& baseNormal, double radius1, double radius2, int approx);
    static UeBody torus(const UeLine3d&axis, double majorRadius, double minorRadius, int majorApprox, int minorApprox);
    static UeBody pipe(const UeLine3d&axis, double outerRadius, double innerRadius, int approx);
    static UeBody pipe(const UeLine3d&axis, const UeVector3d& baseNormal, double outerRadius, double innerRadius, int approx);
    static UeBody pipeConic(const UeLine3d&axis, double outerRadius1, double innerRadius1, double outerRadius2, double innerRadius2, int approx);
    static UeBody pipeConic(const UeLine3d&axis, const UeVector3d& baseNormal, double outerRadius1, double innerRadius1, double outerRadius2, double innerRadius2, int approx);
    static UeBody tetrahedron (const UePoint3d& p1, const UePoint3d& p2, const UePoint3d& p3, const UePoint3d& p4);
    static UeBody reducingElbow(const UePoint3d& elbowCenter, const UePoint3d& endCenter1, const UePoint3d& endCenter2, double endRadius1, double endRadius2, int majorApprox, int minorApprox);
    static UeBody rectangleToCircleReducer(const UePoint3d& baseCorner, const UeVector2d& baseSizes,const UeCircle3d& topCircle,int approx);
    static UeBody convexHull(const UePoint3d pts[], int numPoints);
    static UeBody extrusion (const UePoint3d plg[], UePolygonVertexData* vertexData[],int numVertices,const UeVector3d&plgNormal,const UeVector3d&extrusionVector,const UePoint3d& scaleTwistFixedPt,double scaleFactor,double twistAngle = 0.0);
    static UeBody extrusion (const UePoint3d plg[], UePolygonVertexData* vertexData[],int numVertices,const UeVector3d&plgNormal,const UeVector3d&extrusionVector);
    static UeBody extrusion (const UePoint3d plg[], UePolygonVertexData* vertexData[],int numVertices,const UeVector3d&plgNormal,const UeVector3d&extrusionVector,const std::vector<void*>*attribs);
    static UeBody pyramid(const UePoint3d plg[], UePolygonVertexData* vertexData[], int numVertices, const UeVector3d&plgNormal,const UePoint3d& pyramidApex);
    static UeBody axisRevolution(const UePoint3d plg[], UePolygonVertexData* vertexData[], int numVertices, const UeVector3d& plgNormal, const UeLine3d& axis, double revolutionAngle, int approx, const UePoint3d& scaleTwistFixedPt, double scaleFactor, double twistAngle = 0.0);
    static UeBody axisRevolution(const UePoint3d plg[], UePolygonVertexData* vertexData[], int numVertices, const UeVector3d& plgNormal, const UeLine3d& axis, double revolutionAngle, int approx);
    static UeBody endpointRevolution(const UePoint3d plg[], UePolygonVertexData* vertexData[], int numVertices, const UeVector3d& plgNormal, double revolutionAngle, int approx);
    
    static UeBody extrusionAlongPath(const UeBody& startProfile,const UeBody& endProfile,const UePoint3d pathPlg[], UePolygonVertexData* pathVertexData[],int pathNumVertices,bool pathIsClosed,bool checkBodyValidity = true, const UePoint3d& scaleTwistFixedPt = UePoint3d::kNull, double scaleFactor= 1.0, double twistAngle= 0.0,const UeMorphingMap& morphingMap= UeMorphingMap::kNull,bool calcluateMorphingMapAutomatically = false,std::vector<int>startProfileSignificantVertices= std::vector<int>(), std::vector<int>endProfileSignificantVertices = std::vector<int>());
    static UeBody skin (UeBody* profiles[], int numProfiles, bool isClosed,bool checkPlanarity,UeMorphingMap** morphingMaps = NULL,bool markInnerProfileEdgesAsApprox = false,bool ckeckInputProfiles= true);
    void hideDisplay(const UeTransf3d&projectionTransf,UeOutputPolylineCallback*,bool  = true, UeHiddenLineDrawingImprove = kNoDrawingImprove, UeHideIntegerTransform* = NULL);
    void setHiddenLineParams(UeHiddenLinesDisplay hiddenLinesDisplay = kHiddenLinesInvisible, bool displayApproxEdges = false, bool displayBridgeEdges = false);
    void triangulate(UeOutputTriangleCallback* pCallBack, UeTriangulationType type = kGenerateTriangles,bool  cacheTriangles= true) const;
    void save(UeSaveRestoreCallback* pCallBack) const;
    void save(FILE*)const;
    void save(const wchar_t* fileName) const;
    static UeBody restore(UeSaveRestoreCallback* pCallBack);
    static UeBody restore(FILE*);
    static UeBody restore(const wchar_t* fileName);
    bool  isNull() const;
    UeVertex* vertexList() const;

    // Save to ACIS SAT text file. If colorsAlso is true, every face and edge 
    // receives a color-adesk-attrib
    //
    //void        saveToSat(SaveToSatCallback*,   bool colorsAlso = false) const;
    void        saveToSat(FILE*,                bool colorsAlso = false) const;
    void        saveToSat(const wchar_t* fileName, bool colorsAlso = false) const;

    void     setFaceList      (UeFace*    f) { mpFaceList    = f;    }
//     void     setSurfaceList   (Surface* s) { mpSurfaceList = s;    }
//     void     setCurveList     (Curve*   c) { mpCurveList   = c;    }
    void     setVertexList    (UeVertex*  v) { mpVertexList  = v;    }

    UeFace*    faceList         () const     { return mpFaceList;    }
//     Surface* surfaceList      () const     { return mpSurfaceList; }
//     Curve*   curveList        () const     { return mpCurveList;   }

    void     addFace          (UeFace*   );
    void     addSurface       (UeSurface*);
    void     addCurve         (UeCurve*  );
    void     addVertex        (UeVertex* );


    int      vertexCount  () const;
    int      edgeCount    () const;  
    int      faceCount    () const;
    int      surfaceCount () const;
    int      curveCount   () const;
    int      triangleCount() const;

    void triangulateAllFaces();

private:
    
    UeFace*      mpFaceList;     // Linear list of all faces
    //Surface*   mpSurfaceList;  // Linear list of all surfaces
    //Curve*     mpCurveList;    // Linear list of all curves
    UeVertex*    mpVertexList;   // Linear list of all vertices
    UeBody*      mpNext;         // Next body, currently used only by hideDisplay()

    //Interval3d mInterval;      // Enclosing interval of the body

    UeTriangleCache* mpTriangleCache; 

};  // class Body

AECMODELER_NAMESPACE_END
#endif

